/*
 * Copyright 2015-2019 Evun Technology. 
 * 
 * This software is the confidential and proprietary information of
 * Evun Technology. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with evun.cn.
 */
package cn.evun.sweet.demo.controller;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.evun.sweet.base.util.UserContext;
import cn.evun.sweet.common.util.StringUtils;
import cn.evun.sweet.core.bussinesshelper.GeneralObjectAccessService;
import cn.evun.sweet.core.bussinesshelper.SqlInvokeService;
import cn.evun.sweet.core.common.JsonResultDO;
import cn.evun.sweet.core.common.R;
import cn.evun.sweet.core.context.ContextHolder;
import cn.evun.sweet.core.exception.ValidateException;
import cn.evun.sweet.core.mybatis.common.SqlMapper;
import cn.evun.sweet.core.mybatis.general.Example;
import cn.evun.sweet.core.push.AsyncReqPushManager;
import cn.evun.sweet.core.push.PushMessage;
import cn.evun.sweet.core.validation.ValidateStep;
import cn.evun.sweet.demo.model.OrgDo;
import cn.evun.sweet.demo.model.UserDTO;
import cn.evun.sweet.demo.model.UserDo;
import cn.evun.sweet.demo.services.MainService;

/**
 * 后端演示功能的控制器
 *
 * @author yangw
 * @since 1.0.0
 */
@Controller
public class MainController implements InitializingBean {
	
	@Resource
	private SqlInvokeService sqlInvoker;
	
	@Resource
	private GeneralObjectAccessService objAccessService;
	
	@Resource(name="sqlSession")
	private SqlSession sqlSession; 
	
	@Resource
	private MainService mainServ;
	
	@Autowired
	private AsyncReqPushManager reqMgr;

	/**
	 * 内置登录控制逻辑会在通过登录验证及资源加载后，转向到/main请求。
	 * @throws IOException 
	 */
	@RequestMapping(value="/main")
	public void main(ModelMap model, HttpServletRequest request) throws IOException{
		Properties props = PropertiesLoaderUtils.loadProperties(new DefaultResourceLoader().getResource("conf/sweeter-config.properties"));
		String version = props.getProperty("app.version");
		model.addAttribute("version", version);
	}
	
	/**
	 * 获取当前登录用户的相关信息，加载到$Scope中，可供全局使用。
	 */
	@RequestMapping(value="/main/loginuserinfo")
	@ResponseBody
	public JsonResultDO loginUserinfo(ModelMap model){
		JsonResultDO result = new JsonResultDO();
		result.addAttribute("loginuser",UserContext.getUser(UserDo.class));
		result.addAttribute("tenantname",UserContext.getTenant().getTenantName());
		result.addAttribute("orgname",UserContext.getOrg().getOrgName());
		return result;
	}
	
	/**
	 * 头部需要一些诸如应用切换的信息，所以使用jsp方式。
	 */
	@RequestMapping(value="/blocks/header")
	public void header(ModelMap model){
		model.addAttribute("usercode",UserContext.getUserCode());
	}
	
	
	/*************************************************************************************************************************/
	
	
	/**
	 * 分页查询示例
	 */
	@RequestMapping(value="/jspmode/pagequery")
	public void pageQuery(@RequestParam(value="pageNum",defaultValue="1")Integer pageNum, ModelMap model){
		/*直接调用sql完成查询.此处sql语句无法使用sessionctx的数据,所以需要手动置入*/
		ContextHolder.getContext().setProperty("id", UserContext.getTenantId());
		model.addAttribute("orglist", sqlInvoker.excuteSql("backend.pagequery", pageNum, 5));

		/*通过接口方式完成查询*/
		//model.addAttribute("orglist", mainServ.queryOrgPage(UserContext.getTenantId(), pageNum));
	}
	
	/**
	 * JSP开发模式下常用 BEAN CRUD 示例：查询对象列表主界面
	 */
	@RequestMapping(value="/jspmode/beanlist")
	public void beanList(ModelMap model){
		Example example = new Example(OrgDo.class);
		example.createCriteria().andEqualTo("orgTenantId", UserContext.getTenantId());
		model.addAttribute("orglist", objAccessService.selectByExample(example));
		model.addAttribute("orgcolor", new String[]{"primary", "info", "success", "warning", "danger", "dark"});
	}
	
	/**
	 * JSP开发模式下常用 BEAN CRUD 示例：异步获取查询的内容
	 */
	@RequestMapping(value="/jspmode/userlist")
	@ResponseBody
	public JsonResultDO userList(UserDo user){
		JsonResultDO result = new JsonResultDO();
		result.addAttribute("userlist", objAccessService.queryWithRelation(user==null?UserDo.class:user));
		return result;
	}
	
	/**
	 * JSP开发模式ORM功能示例：查询对象实体
	 */
	@RequestMapping(value="/jspmode/beanmodify", method=RequestMethod.GET)
	public void beanDetail(@RequestParam("userId")Integer userId, ModelMap model){
		//model.addAttribute("user", objAccessService.queryById(UserDo.class, userId));
		model.addAttribute("user", objAccessService.queryByIdWithRelation("user", userId));
		OrgDo org = new OrgDo();
		org.setOrgTenantId(UserContext.getTenantId());
		model.addAttribute("orglist", objAccessService.query(org));
	}
	
	/**
	 * JSP开发模式ORM功能示例：编辑对象实体
	 */
	@RequestMapping(value="/jspmode/beanmodify", method=RequestMethod.POST)
	@ResponseBody
	public JsonResultDO beanModify(@Validated({ValidateStep.First.class, ValidateStep.Third.class}) UserDTO user, 
				BindingResult bresult){
		JsonResultDO result = new JsonResultDO();
		if(bresult.hasErrors()){			
			result.setError(R.message.msgcode_error_validate);
			result.addAttribute("validate", new ValidateException().populate(bresult));
		}else {
			user.setUserModifiedon(new Date());
			objAccessService.modifyByPrimaryKeySelective(user);
		}
		return result;		
	}
	
	/**
	 * JSP开发模式ORM功能示例：删除对象实体（硬删除）
	 */
	@RequestMapping(value="/jspmode/beandel")
	@ResponseBody
	public JsonResultDO beanDel(@RequestParam("userId")Integer[] userId){
		System.out.println("");
		for(int i=0; i<userId.length; i++){
			objAccessService.deleteByPrimaryKey(UserDo.class, userId[i]);
		}
		return new JsonResultDO();
	}
	
	/**
	 * JSP开发模式ORM功能示例：新增对象实体
	 */
	@RequestMapping(value="/jspmode/beanadd", method=RequestMethod.POST)
	@ResponseBody
	public JsonResultDO beanAdd(@Validated({ValidateStep.First.class, ValidateStep.Second.class}) UserDTO user, 
				BindingResult bresult){
		JsonResultDO result = new JsonResultDO();
		if(bresult.hasErrors()){			
			result.setError(R.message.msgcode_error_validate);
			result.addAttribute("validate", new ValidateException().populate(bresult));
		}else {
			UserDo u = new UserDo();
			BeanUtils.copyProperties(user, u);
			objAccessService.addSelective(u.initDefaultInfo());
		}
		return result;
	}
	
	
	/*************************************************************************************************************************/
	
	
	/**
	 * Standard开发模式下,Restfull API示例，获取组织列表信息
	 */
	@RequestMapping(value="/standard/orglist")
	@ResponseBody
	public JsonResultDO orgList(OrgDo org){
		JsonResultDO result = new JsonResultDO();
		if(org == null){
			org = new OrgDo();
		}
		org.setOrgTenantId(UserContext.getTenantId());
		org.setOrgIsdel(false);
		result.addAttribute("orglist", objAccessService.query(org));
		return result;
	}
	
	/**
	 * Standard开发模式下,Restfull API示例，获取用户列表
	 * 注：实际上和jspmode下是一样的，这里更加规范的使用了数据安全性过滤。
	 */
	@RequestMapping(value="/standard/userlist")
	@ResponseBody
	public JsonResultDO restfullUserList(UserDo user){
		JsonResultDO result = new JsonResultDO();
		if(user == null){
			user = new UserDo();
		}
		user.setUserTenantId(UserContext.getTenantId());
		user.setUserIsdel(false);
		result.addAttribute("userlist", objAccessService.queryWithRelation(user));
		return result;
	}
	
	/**
	 * Standard开发模式下,Cache使用实例。查询所有的用户列表。
	 */
	@RequestMapping(value="/standard/contacts")
	@ResponseBody
	public JsonResultDO contactUserList(){
		JsonResultDO result = new JsonResultDO();		
		result.addAttribute("userlist", mainServ.queryUserByCache());		
		return result;
	}
	
	/**
	 * Standard开发模式下,Cache使用实例。保持或更新用户。
	 */
	@RequestMapping(value="/standard/contacts/save")
	@ResponseBody
	public JsonResultDO contactSave(HttpServletRequest request){	
		Map<String, String> user = new HashMap<String, String>(10);
		user.put("group", "杭州测试科技有限公司");
		user.put("name", request.getParameterValues("name")!=null?request.getParameterValues("name")[0]:null);
		user.put("mobile", request.getParameterValues("mobile")!=null?request.getParameterValues("mobile")[0]:null);
		user.put("work", request.getParameterValues("work")!=null?request.getParameterValues("work")[0]:null);
		user.put("home", request.getParameterValues("home")!=null?request.getParameterValues("home")[0]:null);
		user.put("notes", request.getParameterValues("notes")!=null?request.getParameterValues("notes")[0]:null);
		user.put("address", request.getParameterValues("address")!=null?request.getParameterValues("address")[0]:null);
		user.put("email", request.getParameterValues("email")!=null?request.getParameterValues("email")[0]:null);
		mainServ.saveUserByCache(user);	
		return new JsonResultDO();
	}
	
	/**
	 * Standard开发模式下,Cache使用实例。删除用户。
	 */
	@RequestMapping(value="/standard/contacts/del")
	@ResponseBody
	public JsonResultDO contactDelete(String name){		
		mainServ.delUserByCache(name);	
		return new JsonResultDO();
	}
	
	
	/*************************************************************************************************************************/
	
	/**
	 * 使用soap请求获取天气预报信息。
	 */
	@RequestMapping(value="/backcomponent/soap/weather")
	@ResponseBody
	public JsonResultDO getSopeWeather(String cityName, String countryName){
		JsonResultDO result = new JsonResultDO();
		Map<String, String> weather = mainServ.getCityWeather(cityName, countryName);
		result.addAttribute("weather", weather);
		return result;
	}
	
	/**
	 * 使用sqlmapper执行sql语句。
	 */
	@RequestMapping(value="/backcomponent/sqlmapper")
	@ResponseBody
	public JsonResultDO executeSqlMapper(String sql){
		JsonResultDO result = new JsonResultDO();
		SqlMapper sqlExcutor = new SqlMapper(sqlSession);
		List<Map<String, Object>> list = sqlExcutor.selectList(sql);
		result.addAttribute("sqlresult", list);
		return result;
	}
	
	
	/*************************************************************************************************************************/

	@Override
	public void afterPropertiesSet() throws Exception {
		new Thread(new Runnable(){
			@Override
			public void run() {		
				try{
					ServerSocket server = new ServerSocket(5566); 
					Socket client = server.accept();  
			        BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream())); 
			        String[] infos = new String[5];
			        int point = 0;
			        while (!Thread.currentThread().isInterrupted()) {  
			            String info = in.readLine();
			            if("log_split".equals(info.trim())){
			            	point = 0;
			            	PushMessage msg = new PushMessage(10000L, infos[3].trim(), infos[1].toLowerCase().trim(), "log");
				            msg.addAttribute("msgurl", infos[2].trim());
				            msg.addAttribute("msgdate", infos[0].trim());
				            if(StringUtils.hasText(infos[4])){
				            	msg.addAttribute("msgex", infos[4].trim());
				            } 
				            reqMgr.addPushMessage(msg);
			            }else {
			            	if(point < 5){
				            	infos[point] = info;
				            }else {
				            	infos[4] += info;
				            }
			            	point++;
			            } 
			        }  
			        in.close();
			        client.close();
			        server.close();
				}catch(IOException ioex){
					ioex.printStackTrace();
				}
			}			
		}).start();
	}
	
}
